import { reactive, ref, onMounted } from 'vue';

type OrderInfo = {
    sortField?: string;
    sortOrder: 'asc' | 'desc' | '' | null;
};

export type loadDataParam<T extends object = {}> = {
    /** 排序信息 */
    orderParams?: OrderInfo;
    /** 分页信息 */
    pageParams?: {
        pageNo: number;
        pageSize: number;
    };
    /** 筛选信息 */
    queryParams: T;
};

export type loadDataResp<A = unknown> = {
    totalCount?: number;
    dataList: Array<A>;
};

export type loadPaginationRequest<P extends object = {}, R = any> = (
    params: loadDataParam<P>
) => Promise<loadDataResp<R>>;

interface usePaginationConfig {
    /** 表数据获取函数 */
    load: loadPaginationRequest;
    /** 表数据获取检验函数 */
    verifyParameter?(): Promise<object>;
    /** 是否开启分页 */
    paged?: boolean;
    /** 默认排序字段 */
    sortField?: string;
    /** 默认排序方式（asc为正序，desc为倒序） */
    sortOrder?: OrderInfo['sortOrder'];
    /** 初始化组件的适合需要先执行的钩子函数 */
    beforeInit?(): Promise<any>;
    /** 加载完table之后需要先执行的钩子函数 */
    afterLoaded?(): Promise<any>;
}

const usePagination = (tableConfg: usePaginationConfig) => {
    const loading = ref(true);
    const lock = ref(false);
    const oldPage = ref(0);
    const currentPage = ref(1);
    const oldPageSize = ref(10);
    const pageSize = ref(10);
    const totalCount = ref(0);
    const dataList = ref<Awaited<ReturnType<typeof tableConfg.load>>['dataList']>([]);
    const paged = ref(tableConfg.paged);
    const orderInfo = reactive<OrderInfo>({
        sortField: tableConfg.sortField,
        sortOrder: tableConfg.sortOrder ?? null
    });
    const filterParams = ref({});
    /** 查询条件 函数**/
    const searchVerify = tableConfg.verifyParameter;
    const load = tableConfg.load;

    /**
     * 获取表格数据核心方法
     * @param pageNo 当前分页
     * @param pageSize 每页数量
     * @param reload 是否重新加载
     */
    const loadPage = async (pageNo: number, pageSize: number, reload = false) => {
        try {
            /** 页码,页码Size 不变不执行 */
            if (
                oldPage.value === pageNo &&
                oldPageSize.value === pageSize &&
                !reload &&
                paged.value
            ) {
                return Promise.resolve();
            }
            /** 生成查询参数 */
            const params: loadDataParam = { queryParams: filterParams.value };
            params.orderParams =
                orderInfo.sortField != null && orderInfo.sortOrder != null ? orderInfo : undefined;
            paged.value && (params.pageParams = { pageNo, pageSize });
            /** end */
            loading.value = true;
            const { dataList: list, totalCount: count } = await load(params);
            dataList.value = list;
            totalCount.value = count || list.length;
            return Promise.resolve();
        } catch (error) {
            return Promise.reject(error);
        } finally {
            loading.value = false;
        }
    };

    /**
     * 表格分页变化
     * @param {Integer} newCurrentPage 变化后的显示页面
     */
    const onCurrentPageChange = (newCurrentPage: number) => {
        if (lock.value) return Promise.resolve();
        return loadPage(newCurrentPage, pageSize.value)
            .then(() => (oldPage.value = currentPage.value = newCurrentPage))
            .catch(() => (currentPage.value = oldPage.value)); // 失败的话要重置回之前的页码
    };

    /**
     * 表格分页每页显示数量变化
     * @param newPageSize 变化后的每页显示数量
     */
    const onPageSizeChange = (newPageSize: number) => {
        pageSize.value = newPageSize;
        currentPage.value = 1;
        return loadPage(1, newPageSize)
            .then(() => {
                oldPage.value = currentPage.value;
                oldPageSize.value = pageSize.value;
            })
            .catch(() => {
                currentPage.value = oldPage.value;
                pageSize.value = oldPageSize.value;
            });
    };

    /**
     * 表格排序字段变化
     * @param {String} prop 排序字段的字段名
     * @param {String} order 正序还是倒序
     */
    const onSortChange = (prop: string, order: OrderInfo['sortOrder']) => {
        if (!orderInfo.sortField && !prop) return;
        orderInfo.sortField = prop;
        orderInfo.sortOrder = order;
        return refresh(true);
    };

    /**
     *
     * @param research 是否需要重置页码刷新
     * @returns
     */
    const refresh = async (research = false) => {
        try {
            if (research && searchVerify) {
                filterParams.value = await searchVerify();
                dataList.value = [];
            }
            if (research) {
                lock.value = true;
                await loadPage(1, pageSize.value, true);
                // 这里进行了页码赋值 会触发起 onCurrentPageChange 函数
                oldPage.value = currentPage.value = 1;
            } else {
                // 当前页刷新
                await loadPage(currentPage.value, pageSize.value, true);
            }
            if (tableConfg.afterLoaded) return tableConfg.afterLoaded();
            return Promise.resolve();
        } catch (error) {
            return Promise.reject(error);
        } finally {
            lock.value = false;
        }
    };

    const reset = () => {
        oldPage.value = 0;
        currentPage.value = 1;
        totalCount.value = 0;
        orderInfo.sortField = undefined;
        orderInfo.sortOrder = null;
    };

    const setLoading = (isLoading: boolean) => {
        loading.value = isLoading;
    };

    onMounted(() => {
        if (tableConfg.beforeInit) tableConfg.beforeInit();
    });

    const tableInstance = ref({
        loading,
        oldPage,
        totalCount,
        currentPage,
        pageSize,
        dataList,
        reset,
        refresh,
        onCurrentPageChange,
        onPageSizeChange,
        onSortChange,
        setLoading
    });

    return tableInstance;
};

export default usePagination;
